{***************************************************************
    SpyGestion  Copyright (C) 2008 Christophe KOALI <nature2gas@gmail.com>
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
****************************************************************}
unit modParsingClassIApercu;

interface

uses modParsingClassBase,
     modBaseType,
     Classes,
     sFonctionsChaines,
     SysUtils,
     Windows,

     modApercuMsg,

     LibXmlParser;

     
(*******************************************************************************
 Fonctions obligatoires:
   -> Pouvoir détecter les attaques ennemies et sur quelle planète ou lune elle
      est subie
   -> Déterminer les vaisseaux attaquants pour être capable de définir si l'on
      doit évacuer la flotte à quai de la planète/lune attaquée ou non
   -> Déterminer dans combien de temps l'impact à lieu


 Fonctions optionnelles:
   -> Extraire le nom des planètes concernées
   -> Extraire le mouvement de ses propres flottes
   -> Reconstitution exacte du message

   Parmis les fonctions optionnelles, l'extraction du nom de la planète est
   en réalité OBLIGATOIRE car cela permet de savoir si c'est vraiment une planète
   ou si c'est une lune.

 Changements dans la version 0.77:
   -> Les tooltips ont été modifié
   -> Les messages de retour de flotte ne possèdent à présent UNIQUEMENT les
      coordonnées (et avec le nom) de la planète/lune de retour
      

*******************************************************************************)

type

    TParsingApercu = class(IParsingRedirection)
    private

       //
       // Informations qui vont être extraites
       //

       // La liste de messages
       FMessageList: TCollectionAppMessage;


       // Occupations
       FCasesOccupees: integer;
       FCasesTotal   : integer;

       // Points et classement
       FPoints      : integer;
       FClassementPosition: integer;
       FClassementTotalPlayers: integer;

       // Nom
       FCurrNomPlanete: string;
       FCurrNomJoueur: string;

       // Date du serveur (très important)
       FDateServeur: int64;

       // si c'est une lune
       FIsLune: boolean;

       // Dans une attaque groupée, il y a la chaine <br> et les flottes sont
       // dans une meme cellule du tableau
       FCurrAttackGroup: integer;







       //
       // Variables qui vont aider à se repérer dans la page
       //

       FInDataUtile      : boolean;
       FInTable          : integer;
       FWhatIsNextContent: integer;

       FTable1Ligne  : integer;
       FTable1Colonne: integer;
       FTable1ColonneSpan: integer;
       FInFont : boolean;


       FThisLigneIsFlotte: boolean;
       FContentPos: integer;


       FNotFromSpanChecked: boolean;

       FTypeMsg : integer;




       //
       // Variables qui vont servir à extraire les données
       //

       FTitleBaliseA: string;
       FRealTitleBaliseA: string;
       FSpanClass   : string;
       FAClass : string;
       FTamponTraitement: string;

       FAppFlotteMsg: TAppMessage;



       // Version 0.76
       // Modification dans le jeu: Les coordonnées sont encadrées d'une balise <A>
       // c'est à dire d'un lien permettant de voir le système solaire correspondant
       //
       // Pour faire une adaptaton très simple, on bufferise les données
       FFlotteBuffer: string;



   
       //
       // Variables de paramètres du parsing
       //

       FOverrideSpanClassOrdre    : boolean;
       FOverrideSpanClassDirection: boolean;

       FUseSpanClass_AND_MsgGame_If_Fail: boolean;



       procedure ExtractPointClassement(Tampon: string);
       procedure ExtractCasesDiametre;

       procedure InitMsgFlotte(bDoNotResetDateEtDuree: boolean = true);
       
       //procedure GestionMsgAutreJoueur(Content: string);
       function GestionMsgFlotteAutreJoueur(Content: string): boolean;
       function GestionMsgFlotteLaNotre(Content: string): boolean;
    public
       property MsgList : TCollectionAppMessage read FMessageList;
       
       property CasesOccupees: integer       read FCasesOccupees  write FCasesOccupees;
       property CasesTotales : integer       read FCasesTotal     write FCasesTotal;
       property Points : integer             read FPoints         write FPoints;

       property ClassementPosition: integer  read FClassementPosition      write FClassementPosition;
       property ClassementNbJoueurs: integer read FClassementTotalPlayers  write FClassementTotalPlayers;

       property ServeurDate: int64 read FDateServeur;

       property NomPlanete: string   read FCurrNomPlanete  write FCurrNomPlanete;
       property NomJoueur: string    read FCurrNomJoueur   write FCurrNomJoueur;




       /////////////////////////////////////////////////////////////////////////
       // Implémentation de IParsingRedirection

        // initialise l'interface
        procedure Initialisation; override;

        // obtient le résultat d'analyse
        function  GetFinalState: TParsingResultState; override;

        procedure SetFullURLFromBase(const BaseLink: string); override;


        procedure ScanOnStartTag(Sender: TObject; TagName: string; Attributes: TAttrList); override;
        procedure ScanOnEndTag(Sender: TObject; TagName: string); override;
        procedure ScanOnContent(Sender: TObject; Content: string); override;

       //
       /////////////////////////////////////////////////////////////////////////

       
       constructor Create; 
       destructor Destroy; override;
    end;

    function GetVaisseauxStrFromJS(const MsgJS: string; var NbVaisseaux: integer): string;
    
implementation

uses modLanguageParsing,
     sHTMLFonctions,

     ESBDates,
     modCore;


     
const
    // Valeur possible pour FTypeMsg de Apercu
    CNT_FLOTTE_TYPEMSG_TRANSPORTPLANETE_ALLER = 1;
    CNT_FLOTTE_TYPEMSG_TRANSPORTALLIE_ALLER   = 2;
    CNT_FLOTTE_TYPEMSG_ENNEMI_ALLER           = 3;



    LANG_PLANET_PARSING_ADD_INVALID     = ' (invalid language file)';


const
    CNT_NEXT_CONTENT_UNKNOW       = 0;
    CNT_NEXT_CONTENT_PLANETNAME   = 1;
    CNT_NEXT_CONTENT_PSEUDOJOUEUR = 2;
    CNT_NEXT_CONTENT_NEWMESSAGE   = 3;
    CNT_NEXT_CONTENT_POINTS       = 4;
    CNT_NEXT_CONTENT_IN_DIAMETRE  = 5;
    CNT_NEXT_CONTENT_IN_DIAMETRE_BUF  = 6;
    CNT_NEXT_CONTENT_SERVER_TIME   = 7;

    CNT_NEXT_CONTENT_POINTS_PLACE     = 10;
    CNT_NEXT_CONTENT_POINTS_NBPLAYERS = 11;

     
const
    // Identifié comme own flotte:
    APERCU_SPAN_CLASS_OWN_TRANSPORT        = 'flight owntransport';
    APERCU_SPAN_CLASS_OWN_TRANSPORT_RETOUR = 'return owntransport';

    APERCU_SPAN_CLASS_OWN_STATIONNER         = 'flight owndeploy';
    APERCU_SPAN_CLASS_OWN_STATIONNER_RETOUR  = 'return owndeploy';


    APERCU_SPAN_CLASS_OWN_RECYCLAGE        = 'flight ownharvest';
    APERCU_SPAN_CLASS_OWN_RECYCLAGE_RETOUR = 'return ownharvest';

    APERCU_SPAN_CLASS_OWN_ESPIONAGE        = 'flight ownespionage';
    APERCU_SPAN_CLASS_OWN_ESPIONAGE_RETOUR = 'return ownespionage';

    APERCU_SPAN_CLASS_OWN_ATTAQUE        = 'flight ownattack';
    APERCU_SPAN_CLASS_OWN_ATTAQUE_RETOUR = 'return ownattack';

    APERCU_SPAN_CLASS_OWN_COLONISATION = 'flight owncolony';
    APERCU_SPAN_CLASS_OWN_COLONISATION_RETOUR = 'return owncolony';




    // Flotte ennemi mechante:
    APERCU_SPAN_CLASS_ENNEMI_ATTACK              = 'flight attack';
    APERCU_SPAN_CLASS_ENNEMI_SPYING              = 'flight espionage';

    APERCU_SPAN_CLASS_ENNEMI_ATTACK_GROUP        = 'flight federation';


    // Flotte ennemi pacifique:
    APERCU_SPAN_CLASS_ENNEMI_TRANSPORT_PACIFIQUE = 'flight transport';


function AdaptationConversionVaisseauxToNormalStr(Buffer: string): string;
var xPos: integer;
    s: string;
    pBuff: PChar;

    InChiffre: boolean;
begin
   // pour traiter ce champ:
   // title='Small Cargo 1Light Fighter 1'>
   // on a alors:
   // Buffer := 'Small Cargo 1Light Fighter 1';
   // que l'on doit transformer en:
   // 'Small Cargo:1 Light Fighter:1

   pBuff := PChar(Buffer);
   Result := '';
   InChiffre := false;

   while pBuff^ <> #0 do begin
      if (pBuff^ > '9') or (pBuff^ < '0') then begin

         if InChiffre then begin
            // début d'un autre type de vaisseau
            // ajoute un espace
            // puis la lettre
            Result := Result + '; ' + pBuff^;

            InChiffre := false;
            
         end else begin
            Result := Result + pBuff^;

         end;


      end else begin
         if InChiffre = false then begin
            // efface l'espace de droite pour s'assurer qu'il y en a qu'un seul
            Result := trim(Result);

            // ajoute le chiffre et s'assure d'un espace
            Result := Result + ' ' + pBuff^;

            InChiffre := true;
            
         end else begin
            // ajoute juste le chiffre
            Result := Result + pBuff^;
         end;

      end;


      Inc(pBuff);
   end;

end;

procedure TParsingApercu.SetFullURLFromBase(const BaseLink: string);
begin
    // rien à faire
    inherited;
end;

procedure TParsingApercu.Initialisation;
begin

       inherited;

       //
       // Informations qui vont être extraites
       //


       // La liste de messages
       FMessageList.Clear;


       // Occupations
       FCasesOccupees:= -1;
       FCasesTotal   := -1;

       // Points et classement
       FPoints       := -1;
       FClassementPosition     := -1;
       FClassementTotalPlayers := -1;

       // Nom
       FCurrNomPlanete := '';
       FCurrNomJoueur  := '';

       // Date du serveur (très important)
       FDateServeur    := 0;

       // si c'est une lune
       FIsLune := false;

       // Dans une attaque groupée, il y a la chaine <br> et les flottes sont
       // dans une meme cellule du tableau
       FCurrAttackGroup  := 0;




       //
       // Variables qui vont aider à se repérer dans la page
       //

       FInDataUtile := false;
       FInTable     := 0;
       FWhatIsNextContent:= CNT_NEXT_CONTENT_UNKNOW;


       FTable1Ligne      := -1;
       FTable1Colonne    := -1;
       FTable1ColonneSpan:= -1;
       FInFont := false;


       FThisLigneIsFlotte := false;
       FContentPos        := 0;

       // initialisation sur le vol
       FNotFromSpanChecked:= false;

       FTypeMsg := -1;





       //
       // Variables qui vont servir à extraire les données
       //

       FTitleBaliseA     := '';
       FSpanClass        := '';
       FAClass           := '';
       FTamponTraitement := '';

       //FAppFlotteMsg: TAppMessage;



       // Version 0.76
       // Modification dans le jeu: Les coordonnées sont encadrées d'une balise <A>
       // c'est à dire d'un lien permettant de voir le système solaire correspondant
       //
       // Pour faire une adaptaton très simple, on bufferise les données
       FFlotteBuffer     := '';



       FError := false;





end;

function TParsingApercu.GetFinalState: TParsingResultState;
var pe: PAppMessage;
    i: integer;
begin
    Result := PRESULT_ECHEC;

       // OVERRIDDING pour la mise à jour
       FError := false;

       // TEMPORAIREMENT: On supprime les messages de retour
       if FMessageList.Count > 0 then begin
          for i := FMessageList.Count - 1 downto 0 do begin
             pe := FMessageList.Items[i];

             if pe.Direction = odRetour then begin
                FMessageList.Delete(i);
             end;
          end;
       end;



       if FDateServeur < 500 then begin
          DoDebugContent('Erreur: Date serveur invalide');
          FError := true;
       end;




       
       if FCurrNomPlanete = '' then begin
          DoDebugContent('Erreur: Nom de planète vide');
          //FError := true;
       end;

       if FCasesTotal < 1 then begin
          // c'est une erreur

          if FCasesTotal < 0 then begin
             DoDebugContent('Erreur: Nombre de cases totales négatif');
             FError := true;

          end else begin
             DoDebugContent('Attention: Moins d''une case au total sur la planète (plus considéré comme une erreur)');
          end;


       end else if FCasesTotal < 2 then begin
          // c'est peut-être une nouvelle lune

          if pos(LangParsing.GetData('apercu_LunePosFi', 'une'), FCurrNomPlanete) <= 1 then begin
             // ce n'est pas une lune
             DoDebugContent('Attention: Moins de 2 cases au total sur la planète (plus considéré comme une erreur)');

             //FError := true;

          end;


       end;





       //
       // Classement
       //

       if FPoints < 0 then begin
          DoDebugContent('Erreur: Nombre de points négatif');
          FError := true;
       end;

       if FClassementTotalPlayers < 0 then begin
          DoDebugContent('Erreur: Nombre de joueur total invalide');
          FError := true;
       end;


       if FClassementPosition < 0 then begin
          DoDebugContent('Erreur: Classement invalide');
          FError := true;
       end;


       if FError then begin
          exit;
       end;



    Result := NoT(PRESULT_ECHEC);
end;

procedure TParsingApercu.ExtractCasesDiametre;
var xPos, i: integer;
    s: string;
begin
// 17800 km     ( <a title="Cases occupées"> 85 </a> / <a title="nombre maximal des cases utilisables">193 </a> cases )
// sans les balises et espace entre "contenu", ce qui donne:
// 17800 km     (85/193cases)


    xPos := pos('(', FTamponTraitement);
    if xPos = 0 then exit;

    System.Delete(FTamponTraitement, 1, xPos);

    xPos := pos('/', FTamponTraitement);
    if xPos = 0 then exit;

    s := copy(FTamponTraitement, 1, xPos - 1);
    FCasesOccupees := StrToIntDef(s, -1);

    if FCasesOccupees < 0 then exit;

    System.Delete(FTamponTraitement, 1, xPos);

    i := 1;
    s := '';
    while (i <= length(FTamponTraitement)) do begin
       if FTamponTraitement[i] in sfc_ChiffresSet then
          s := s + FTamponTraitement[i]
       else
          break;

       Inc(i);
    end;

    FCasesTotal := StrToIntDef(s, -1);

    FTamponTraitement := '';
end;


procedure TParsingApercu.ExtractPointClassement(Tampon: string);
var xPos: integer;
    s: string;
begin
    // 1045 (Place 4127 de 10915)
    // 151 (Rank 6931 of 13071)
    // ATTENTION: Il se peut que l'ordre des nombres soit inversé
    // dans certain univers

    Tampon := trim(Tampon);

    xPos := pos(' ', Tampon);
    if xPos = 0 then exit;

    s := copy(Tampon, 1, xPos - 1);
    System.Delete(Tampon, 1, xPos);

    FPoints := StrToIntDef(s, -1);


    // (Place 4127 de 10915)
    // (Rank 6931 of 13071)
    xPos := pos(' ', Tampon);
    if (xPos = 0) or (FPoints < 0) then exit;
    System.Delete(Tampon, 1, xPos);
    Tampon  := trimleft(Tampon);

    xPos := pos(' ', Tampon);
    if (xPos = 0) then exit;
    s := copy(Tampon, 1, xPos - 1);
    System.Delete(Tampon, 1, xPos);

    FClassementPosition := StrToIntDef(s, -1);

    // de 10915)
    // of 13071)
    xPos := pos(')', Tampon);
    if (xPos = 0) or (FClassementPosition < 0) then exit;
    System.Delete(Tampon, xPos, maxint);

    xPos := LastDelimiter(' ', Tampon);
    if xPos = 0 then exit;

    s := copy(Tampon, xPos + 1, maxint);
    FClassementTotalPlayers := StrToIntDef(s, -1);

end;



procedure TParsingApercu.InitMsgFlotte(bDoNotResetDateEtDuree: boolean = true);
begin
    with FAppFlotteMsg do begin

         if bDoNotResetDateEtDuree then begin
            Duree      := -1;
            DateImpact := 0;
         end;

         Ordre     := ooNeant;
         Direction := odNeant;

         bColorMenace := false;
         bOwnFlotte   := false;

         PlayerFlotte := '';

         Depart.Galaxie  := -1;
         DepartStr       := '';
         Arrivee.Galaxie := -1;
         ArriveeStr      := '';

         NbVaisseau := -1;
         VaisseauxStr := '';
         Msg := '';
    end;

    FTypeMsg := -1;

end;



procedure TParsingApercu.ScanOnStartTag(Sender: TObject; TagName: string; Attributes: TAttrList);
var xPos: integer;
    CurrBalise: string;
begin

    TagName := lowercase(TagName);

    if (FInDataUtile = false) and (TagName = 'a') then begin
        // Les données utiles commencent à partir du nom de la planète
        // A ce moment là, on est alors dans une "table"

        // <a href="renameplanet.php?session=0000&pl=1111111" title="Planetenmenü">Planète      &quot;PlaneteNom&quot;</a> (PseudoJoueur)
        // FInDataUtile
        CurrBalise := trim(Attributes.Value('href'));

        // TODO: Sauvegarder ce lien pour permettre le changement de nom de
        // la planète
        CurrBalise := lowercase(CurrBalise);

        if pos('renameplanet', CurrBalise) > 0 then begin
            FInDataUtile := true;

            // et on est donc dans une table
            // ceci n'est plus un boolean car il y a une autre table
            // dans la table
            FInTable := 1;
            FTable1Ligne := 1;

            FWhatIsNextContent := CNT_NEXT_CONTENT_PLANETNAME;
        end;

        exit;
    end;

    if FInDataUtile = false then exit;

    // On ignore les tableaux qui sont inclu dans le tableau utile
    if FInTable > 1 then exit;


    if TagName = 'table' then begin
       Inc(FInTable);


    end else if TagName = 'tr' then begin
       if FWhatIsNextContent = CNT_NEXT_CONTENT_IN_DIAMETRE_BUF then begin
          // Réinitialise le flag
          FWhatIsNextContent := CNT_NEXT_CONTENT_UNKNOW;

          // Traite le tampon
          ExtractCasesDiametre;
       end;


       Inc(FTable1Ligne);
       FTable1Colonne := 0;


       if FThisLigneIsFlotte  and (FAppFlotteMsg.Duree > 0) and (FAppFlotteMsg.Ordre <> ooNeant) and (FAppFlotteMsg.Msg <> '') then begin
          // Message de flotte à gérer
          FMessageList.Add(FAppFlotteMsg);
       end;
       FThisLigneIsFlotte := false;
       InitMsgFlotte;
       FTamponTraitement := '';
       FInFont := false;

       
       FCurrAttackGroup := 0;






    end else if (TagName = 'td') or (TagName = 'th') then begin
       Inc(FTable1Colonne);

       CurrBalise := trim(Attributes.Value('colspan'));

       if CurrBalise = '' then
          FTable1ColonneSpan := 0
       else
          FTable1ColonneSpan := StrToIntDef(CurrBalise, 0);


    end else if TagName = 'div' then begin
       // <div id="bxx1"  title="1204" star="1117845762"></div>

       // Début de mouvement de flotte
       CurrBalise := trim(Attributes.Value('title'));

       if (CurrBalise <> '') and (sfcChaineContientQueDesChiffres(CurrBalise)) then begin
          FThisLigneIsFlotte := true;

          try
             FAppFlotteMsg.Duree := StrToInt(CurrBalise);
          except
             FThisLigneIsFlotte := false;
          end;

          FContentPos := 0;
       end;


       // DateImpact
       //
       CurrBalise := trim(Attributes.Value('star'));
       if FThisLigneIsFlotte and (CurrBalise <> '') and (sfcChaineContientQueDesChiffres(CurrBalise)) then begin
           // il semble que c'est l'heure d'impact sur le serveur
           // c'est d'ailleurs excellent

          try
             FAppFlotteMsg.DateImpact := StrToInt(CurrBalise);
          except
             FAppFlotteMsg.DateImpact := 0;
          end;


       end;



    end else if TagName = 'font' then begin


       if FThisLigneIsFlotte then begin
          FInFont := true;

          CurrBalise := lowercase(trim(Attributes.Value('color')));

          // Ennemi: #ff0000  abrégeable en #ff
          // Ami: #00ff00

       (*
          if copy(CurrBalise, 1, 3) = '#ff' then begin
             FAppFlotteMsg.bColorMenace := true;

          end else if copy(CurrBalise, 1, 5) = '#00ff' then begin
             FAppFlotteMsg.bColorMenace := false;

          end else begin
             FThisLigneIsFlotte := false;
          end;
*)
          
       end;
       
    end else if TagName = 'a' then begin

       // messages
       CurrBalise := trim(Attributes.Value('href'));
       FAClass := trim(Attributes.Value('class'));


       FTitleBaliseA := trim(Attributes.Value('onmouseover'));
       FRealTitleBaliseA := trim(Attributes.Value('title'));

       // TODO: Sauvegarder ce lien pour permettre le changement de nom de
       // la planète
       CurrBalise := lowercase(CurrBalise);

        if pos('messages', CurrBalise) > 0 then begin

            if FThisLigneIsFlotte = false then
               FWhatIsNextContent := CNT_NEXT_CONTENT_NEWMESSAGE;

        end;


    end else if TagName = 'br' then begin

       if FCurrAttackGroup > 0 then begin
          Inc(FCurrAttackGroup);
       end;

    end else if TagName = 'span' then begin
        // <span class='flight attack'>
        FSpanClass := trim(Attributes.Value('class'));

        if FCurrAttackGroup > 2 then begin
           // c'est bien une attaque groupee

           if FThisLigneIsFlotte  and (FAppFlotteMsg.Duree > 0) and (FAppFlotteMsg.Ordre <> ooNeant) and (FAppFlotteMsg.Msg <> '') then begin
              // Message de flotte à gérer
              FMessageList.Add(FAppFlotteMsg);
           end;

           InitMsgFlotte(false);
           FTamponTraitement := '';
           FInFont := false;

           FContentPos := 0;

           // Ce parametre n'est pas reinitialise à false
           FThisLigneIsFlotte := true;


        end;

    end else if TagName = 'script' then begin


    end;


    // renameplanet

end;

procedure TParsingApercu.ScanOnEndTag(Sender: TObject; TagName: string);
begin

    // Ici on ne met pas la condition FInTable > 1, car on attend justement
    // la fin de la table pour continuer, on la met donc plus loin
    if FInDataUtile = false then exit;

    TagName := lowercase(TagName);


    if TagName = 'table' then begin
       Dec(FInTable);


       //FWhatIsNextContent := CNT_NEXT_CONTENT_UNKNOW;
       
       if FInTable = 0 then begin
          // On a finit le travail
          //FScanner.StopParser := true;
          exit;
       end;

    end else if TagName = 'a' then begin
       FTitleBaliseA := '';
       

    end else if TagName = 'font' then begin
       FInFont := false;


    end;

    // Condition qui attend la fin de la table avant de continuer
    if FInTable > 1 then exit;


end;



procedure TParsingApercu.ScanOnContent(Sender: TObject; Content: string);
var xPos: integer;
    lngPos: integer;

    ContentTrimLw, Content1: string;
    bIsFromLune: boolean;

    bChecked: boolean;
begin



    if pos(LangParsing.GetData('apercu_lwpos_heure_serveur', 'heure du serveur'), lowercase(Content)) > 0 then begin
       if FInDataUtile = false then begin
          // on était alors sur une lune
          FCurrNomPlanete := LangParsing.GetData('Lune', 'Lune');
          FIsLune := true;
          FInDataUtile := true;
          FInTable := 1;
          FTable1Ligne := 2;
          FWhatIsNextContent := CNT_NEXT_CONTENT_SERVER_TIME;
          exit;
       end;

    end;

    if FInDataUtile = false then exit;
    if FInTable > 1 then exit;


    if FThisLigneIsFlotte then begin

       Inc(FContentPos);




       if FContentPos = 1 then begin
          // Sauvegarde le texte
          FAppFlotteMsg.Msg := Content;
          FNotFromSpanChecked := false;

          // Met en minuscule la chaine
          ContentTrimLw := lowercase(trim(Content));


          /////////////////////////////////////////////////////
          // PROPRE FLOTTE - DEBUT
          /////////////////////////////////////////////////////
          bChecked := false;

          if  SameText(FSpanClass, APERCU_SPAN_CLASS_OWN_TRANSPORT)        then begin
              FAppFlotteMsg.Ordre      := ooTransport;
              FAppFlotteMsg.Direction  := odAller;
              bChecked := true;

          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_OWN_TRANSPORT_RETOUR) then begin
              FAppFlotteMsg.Ordre      := ooTransport;
              FAppFlotteMsg.Direction  := odRetour;
              bChecked := true;



          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_OWN_STATIONNER)        then begin
              FAppFlotteMsg.Ordre      := ooBaser;
              FAppFlotteMsg.Direction  := odAller;
              bChecked := true;

          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_OWN_STATIONNER_RETOUR) then begin
              FAppFlotteMsg.Ordre      := ooBaser;
              FAppFlotteMsg.Direction  := odRetour;
              bChecked := true;



          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_OWN_RECYCLAGE)        then begin
              FAppFlotteMsg.Ordre      := ooExploiter;
              FAppFlotteMsg.Direction  := odAller;
              bChecked := true;

          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_OWN_RECYCLAGE_RETOUR) then begin
              FAppFlotteMsg.Ordre      := ooExploiter;
              FAppFlotteMsg.Direction  := odRetour;
              bChecked := true;



          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_OWN_ESPIONAGE)        then begin
              FAppFlotteMsg.Ordre      := ooEspionner;
              FAppFlotteMsg.Direction  := odAller;
              bChecked := true;

          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_OWN_ESPIONAGE_RETOUR) then begin
              FAppFlotteMsg.Ordre      := ooEspionner;
              FAppFlotteMsg.Direction  := odRetour;
              bChecked := true;



          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_OWN_ATTAQUE)        then begin
              FAppFlotteMsg.Ordre      := ooAttaquer;
              FAppFlotteMsg.Direction  := odAller;
              bChecked := true;

          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_OWN_ATTAQUE_RETOUR) then begin
              FAppFlotteMsg.Ordre      := ooAttaquer;
              FAppFlotteMsg.Direction  := odRetour;
              bChecked := true;



          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_OWN_COLONISATION)        then begin
              FAppFlotteMsg.Ordre      := ooColoniser;
              FAppFlotteMsg.Direction  := odAller;
              bChecked := true;

          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_OWN_COLONISATION_RETOUR) then begin
              FAppFlotteMsg.Ordre      := ooColoniser;
              FAppFlotteMsg.Direction  := odRetour;
              bChecked := true;




          end else if FUseSpanClass_AND_MsgGame_If_Fail or (FSpanClass = '')  then begin
              // determine à partir du message


              if SameText(ContentTrimLw, LangParsing.GetData('apercu_st_une_de_vos', 'Une de vos')) or SameText(ContentTrimLw, LangParsing.GetData('apercu_st_une_de_tes', 'Une de tes')) then begin
                 FAppFlotteMsg.Ordre      := ooNeant;
                 FAppFlotteMsg.Direction  := odNeant;
                 bChecked := true;
                 FNotFromSpanChecked := true;
              end;

          end;

// Francais:
// <span class='flight owntransport'>Une de tes <a href='#' onmouseover='this.T_WIDTH=150;return escape("Petit transporteur 56&lt;br&gt;Grand transporteur 90&lt;br&gt;")' class='owntransport'>flottes</a><a href='' title='Petit transporteur 56Grand transporteur 90'></a> venant de la planète planetName [5:265:5] atteint la  lune [5:265:5]. Elle avait pour mission: <a href='#' onmouseover='this.T_WIDTH=150;return escape("Transporter: &lt;br /&gt; Métal: 1500000&lt;br /&gt;Cristal: 500000&lt;br /&gt;Deutérium: 0")' class='owntransport'>Transporter</a><a href='#' title='Transporter: Métal: 1500000 Cristal: 500000 Deutérium: 0'></a></span>
// Anglais:
// <span class='flight owntransport'>One of your <a href='#' onmouseover='this.T_WIDTH=150;return escape("Small Cargo 1&lt;br&gt;")' class='owntransport'>fleets</a><a href='' title='Small Cargo 1'></a> from planet planetName [5:8:9] reaches planet planetName [5:14:9]. Its mission is: Transport.</span>
// Espagnol:
// <span class="flight owntransport">Una de tus <a href="#" onmouseover='this.T_WIDTH=150;return escape("Sonda de espionaje 4<br>")' class="owntransport">flotas</a><a href="" title="Sonda de espionaje 4"></a> de el planeta planetName [3:77:12] llega a el planeta planetName [3:52:4]. La misión es: <a href="#" onmouseover='this.T_WIDTH=150;return escape("Transportar: <br /> Metal: 300<br />Cristal: 300<br />Deuterio: 700")' class="owntransport">Transportar</a><a href="#" title="Transportar: Metal: 3 Cristal: 3 Deuterio: 7"></a></span>


          if bChecked then begin
             // Action avec ses propres flottes
             FAppFlotteMsg.bOwnFlotte := true;
             FAppFlotteMsg.bColorMenace := false;

             FTypeMsg := CNT_FLOTTE_TYPEMSG_TRANSPORTPLANETE_ALLER;
             exit;
          end;






          /////////////////////////////////////////////////////
          // ENNEMI FLOTTE HOSTILE - DEBUT
          // Attaque ou sondage
          /////////////////////////////////////////////////////

          bChecked := false;
          if SameText(FSpanClass, APERCU_SPAN_CLASS_ENNEMI_ATTACK) then begin
             // verifié par la class d'affichage de couleur
             FAppFlotteMsg.Ordre := ooAttaquer;
             bChecked := true;


          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_ENNEMI_ATTACK_GROUP) then begin
             // verifié par la class d'affichage de couleur
             FAppFlotteMsg.Ordre := ooAttaquer;
             FCurrAttackGroup := 1;
             bChecked := true;


          end else if SameText(FSpanClass, APERCU_SPAN_CLASS_ENNEMI_SPYING) then begin
             // verifié par la class d'affichage de couleur
             FAppFlotteMsg.Ordre := ooEspionner;
             bChecked := true;


          end else if FUseSpanClass_AND_MsgGame_If_Fail or (FSpanClass = '')  then begin

             if SameText(ContentTrimLw, LangParsing.GetData('apercu_lw_ennemi_flotte', 'une')) then begin
                FAppFlotteMsg.Ordre := ooNeant;
                bChecked := true;
                FNotFromSpanChecked := true;
             end;

          end;

// Français (attaque):
// <span class='flight attack'>Une <a href='#' onmouseover='this.T_WIDTH=150;return escape("Nombre de vaisseaux: 1666 &lt;br&gt;Chasseur léger 1666&lt;br&gt;")' class='attack'>flotte</a><a href='' title='Nombre de vaisseaux: 1666 Chasseur léger 1666'></a> hostile de scoubidou <a href='writemessages.php?session=11111&messageziel=00000'><img src='http://jjjjjjj/download/use/asgard/img/m.gif' title='Ecrire un message' alt='Ecrire un message'></a> venant de la planète planetName [5:187:4] atteint la planète planetName [5:165:5]. Elle avait pour mission: Attaquer</span>

// Anglais (Attaque):
// <span class='flight attack'>A hostile <a href='#' onmouseover='this.T_WIDTH=150;return escape("Number of ships 4 &lt;br&gt;")' class='attack'>fleet</a><a href='' title='Number of ships 4 '></a> from Nuada Silver Hand <a href='writemessages.php?session=11111111&messageziel=00000000'><img src='http://yyyyyyyyyyyyyy/epicblue/img/m.gif' title='write message' alt='write message'></a> from planet planetName [5:67:8] is approaching planet planetName [1:77:9]. Its mission is: Attack.

// Espagnol (espionnage):
// <span class="flight espionage">Una <a href="#" onmouseover='this.T_WIDTH=150;return escape("Número de naves: 2 <br>Nave grande de carga <br>Sonda de espionaje <br>")' class="espionage">flota</a><a href="" title="Número de naves: 2 Nave grande de carga Sonda de espionaje "></a> enemiga de Krip <a href="http://xxxxxxxxx/game/writemessages.php?session=00000000&amp;messageziel=11111111"><img src="overview_data/m.gif" title="Escribir mensaje" alt="Escribir mensaje"></a> de el planeta planetName [7:481:6] llega a el planeta planetName [1:301:10]. La misión es: Espionaje</span>
// Espagnol (attaque):
// <span class="flight attack">Una <a href="#" onmouseover='this.T_WIDTH=150;return escape("Número de naves: 8 <br>Nave grande de carga <br>Cazador ligero <br>Sonda de espionaje <br>")' class="attack">flota</a><a href="" title="Número de naves: 8 Nave grande de carga Cazador ligero Sonda de espionaje "></a> enemiga de Krip <a href="http://xxxxxxxxx/game/writemessages.php?session=000000000&amp;messageziel=111111111"><img src="overview_data/m.gif" title="Escribir mensaje" alt="Escribir mensaje"></a> de el planeta planetName [7:56:6] llega a el planeta planetName [1:77:10]. La misión es: Atacar


          if bChecked then begin
             // La flotte gueriere est toujours vu dans le sens "aller"
             FAppFlotteMsg.Direction  := odAller;

             FAppFlotteMsg.bOwnFlotte := false;
             FAppFlotteMsg.bColorMenace := true;

             FTypeMsg := CNT_FLOTTE_TYPEMSG_ENNEMI_ALLER;
             exit;
          end;








          /////////////////////////////////////////////////////
          // ENNEMI FLOTTE PACIFIQUE - DEBUT
          /////////////////////////////////////////////////////
          bChecked := false;

          if SameText(FSpanClass, APERCU_SPAN_CLASS_ENNEMI_TRANSPORT_PACIFIQUE) then begin
             // verifie par la class d'affichage de couleur
             bChecked := true;
             FAppFlotteMsg.Ordre := ooTransport;
             
          end else if FUseSpanClass_AND_MsgGame_If_Fail or (FSpanClass = '')  then begin

             if pos(LangParsing.GetData('apercu_poslw_pacifique_flotte', 'une pacifique flotte'), ContentTrimLw) > 0 then begin
                bChecked := true;
                FAppFlotteMsg.Ordre := ooNeant;
             end;

          end;

// Français:
// <span class='flight transport'>Une <a href='#' onmouseover='this.T_WIDTH=150;return escape("Nombre de vaisseaux: 1 &lt;br&gt;Chasseur léger &lt;br&gt;")' class='transport'>flotte</a><a href='' title='Nombre de vaisseaux: 1 Chasseur léger '></a> pacifique de XXXXXXX <a href='writemessages.php?session=111111&messageziel=100000000'><img src='http://127.0.0.1/ogame/skinx/img/m.gif' title='Ecrire un message' alt='Ecrire un message'></a> venant de la planète planetName [1:89:6] atteint la planète planetName [1:93:14]. Elle avait pour mission: Transporter</span>
// Espangol:
// <span class="flight transport">Una <a href="#" onmouseover='this.T_WIDTH=150;return escape("Número de naves: 1 <br>Nave grande de carga <br>")' class="transport">flota</a><a href="" title="Número de naves: 1 Nave grande de carga "></a> pacífica de Krip <a href="http://000000000000.de/game/writemessages.php?session=1111111111&amp;messageziel=00000000"><img src="overview_data/m.gif" title="Escribir mensaje" alt="Escribir mensaje"></a> de el planeta planetName [8:54:6] llega a el planeta planetName [8:67:10]. La misión es: Transportar</span>
// Anglais:
// <span class='flight transport'>A friendly <a href='#' onmouseover='this.T_WIDTH=150;return escape("")' class='transport'>fleet</a><a href='' title=''></a> from Atticus <a href='writemessages.php?session=0111111&messageziel=1111111111'><img src='http://yyyyyyyyyyyyy.de/epicblue/img/m.gif' title='write message' alt='write message'></a> from planet planetName [1:24:12] is approaching planet planetName [1:29:9]. Its mission is: Transport.</span>


          if bChecked then begin
             // La flotte alliées est toujours vu dans le sens "aller"
             FAppFlotteMsg.Direction    := odAller;
             FAppFlotteMsg.bOwnFlotte   := false;
             FAppFlotteMsg.bColorMenace := false;

             FTypeMsg := CNT_FLOTTE_TYPEMSG_TRANSPORTALLIE_ALLER;

             exit;
          end;


          // Sinon, erreur...




          
       end else begin
          // C'est un message suivant
          // Sauvegarde le texte
          FAppFlotteMsg.Msg := FAppFlotteMsg.Msg + ' ' + Content;


          case FTypeMsg of



          /////////////////////////////////////////////////////
          // PROPRE FLOTTE - SUITE
          /////////////////////////////////////////////////////
              CNT_FLOTTE_TYPEMSG_TRANSPORTPLANETE_ALLER: begin



                         if FContentPos = 2 then begin
                            // Content ne contient que le mot "flottes"
                            // Il y a rien à faire
                            // On rajoute dans FAppFlotteMsg.Msg le contenu de title de la balise A.

                            if FTitleBaliseA <> '' then begin
                               FAppFlotteMsg.Msg := FAppFlotteMsg.Msg + ' (' + FTitleBaliseA + ')';

                               FAppFlotteMsg.VaisseauxStr := FTitleBaliseA;

                               // Calcul le nombre de vaisseaux ici
                               FAppFlotteMsg.NbVaisseau := mamCalculNbVaisseauxOwnFlotteV73c(FAppFlotteMsg.VaisseauxStr);
                               // Grand transporteur 12; Croiseur 15; Vaisseau de bataille 40

                            end;


                         end else if FContentPos = 3 then begin
                            FFlotteBuffer := Content;

                            FAppFlotteMsg.VaisseauxStr := AdaptationConversionVaisseauxToNormalStr(FRealTitleBaliseA);
                            FAppFlotteMsg.NbVaisseau   := mamCalculNbVaisseauxOwnFlotteV73c(FAppFlotteMsg.VaisseauxStr);

                         end else if (FContentPos = 4) or
                                     (FContentPos = 5) then begin

                            // 4: coord
                            // 5: suite

                            FFlotteBuffer := FFlotteBuffer + ' ' + Content;

                         end else if FContentPos = 6 then begin
                            // 6: coord

                            FFlotteBuffer := FFlotteBuffer + ' ' + Content;

                            GestionMsgFlotteLaNotre(FFlotteBuffer);

                            FFlotteBuffer := '';

                            // 7: Mission start
                            // 8: mission

                         end else if FContentPos = 8 then begin
                            // Normalement il ne reste plus que l'ordre, qui devrait être "Transport"
                            // <a href="#" title="Deutérium: 60.001">Transport
                            // <br />

                            if FTitleBaliseA <> '' then begin
                               FTitleBaliseA := sfcRemplace(FTitleBaliseA, '<br />', '; ');
                               FTitleBaliseA := sfcRemplace(FTitleBaliseA, '<br >', '; ');
                               FTitleBaliseA := sfcRemplace(FTitleBaliseA, '<br>', '; ');
                               FTitleBaliseA := sfcRemplace(FTitleBaliseA, ': ;', ': ');
                               FTitleBaliseA := sfcRemplace(FTitleBaliseA, ':;', ':');

                               FTitleBaliseA := sfcRemplace(FTitleBaliseA, '   ', ' ');
                               FTitleBaliseA := sfcRemplace(FTitleBaliseA, '  ', ' ');
                               FTitleBaliseA := sfcRemplace(FTitleBaliseA, '")', '');

                               FAppFlotteMsg.Msg := FAppFlotteMsg.Msg + ' (' + FTitleBaliseA + ')';

                            end;


                            if (FAppFlotteMsg.Ordre = ooNeant) or FOverrideSpanClassOrdre then begin
                               // l'ordre n'a pas été trouvé avec le SPAN CLASS
                               FAppFlotteMsg.Ordre := mamOrdreStrToType(Content);
                            end;

                            
                         end;


                     end;



          /////////////////////////////////////////////////////
          // ENNEMI FLOTTE HOSTILE - SUITE
          // Attaque ou sondage
          /////////////////////////////////////////////////////

              CNT_FLOTTE_TYPEMSG_ENNEMI_ALLER: begin


                         if FContentPos = 2 then begin
                            // contient seulement le mot "flotte"
                            FAppFlotteMsg.VaisseauxStr := GetVaisseauxStrFromJS(FTitleBaliseA, FAppFlotteMsg.NbVaisseau );
                            FRealTitleBaliseA := '';

                            
                         end else if FContentPos = 3 then begin
                            // Exemple: "hostile de xxx"

                            // Contient le pseudo de l'attaquant
                            // le pseudo peut contenir des espaces
                            // A ADAPTE en fonction des langues:
                            FAppFlotteMsg.PlayerFlotte := sfcTokenGet(Content, -3, ' ');

                            // TODO: Expérimental, à vérifier
                            if FRealTitleBaliseA <> '' then begin
                               FAppFlotteMsg.VaisseauxStr := AdaptationConversionVaisseauxToNormalStr(FRealTitleBaliseA);
                               FAppFlotteMsg.NbVaisseau   := mamCalculNbVaisseauxOwnFlotteV73c(FAppFlotteMsg.VaisseauxStr);
                            end;


                         end else if FContentPos = 4 then begin
                            // Contient les coordonnées de départ/arrivée
                            FFlotteBuffer := Content;

                         end else if (FContentPos = 5) or
                                     (FContentPos = 6)  then begin
                            // 5: coord
                            // 6: suite
                            FFlotteBuffer := FFlotteBuffer + ' ' + Content;


                         end else if FContentPos = 7 then begin
                            // 7: coord
                            FFlotteBuffer := FFlotteBuffer + ' ' + Content;

                            GestionMsgFlotteAutreJoueur(FFlotteBuffer);

                         end;

                     end;




          /////////////////////////////////////////////////////
          // ENNEMI FLOTTE PACIFIQUE - DEBUT
          /////////////////////////////////////////////////////
              CNT_FLOTTE_TYPEMSG_TRANSPORTALLIE_ALLER: begin
                         if FContentPos = 2 then begin
                            // contient seulement le mot "flotte"
                            FAppFlotteMsg.VaisseauxStr := GetVaisseauxStrFromJS(FTitleBaliseA, FAppFlotteMsg.NbVaisseau );


                            
                         end else if FContentPos = 3 then begin
                            // Exemple: "pacifique de xxx"

                            // Contient le pseudo de l'attaquant
                            // le pseudo peut contenir des espaces
                            // A ADAPTE en fonction des langues
                            // NE PAS COMETTRE L'ERREUR de fusionner le code
                            // avec CNT_FLOTTE_TYPEMSG_ENNEMI_ALLER car il est
                            // similaire, mais il se peut qu'il ne le soit pas
                            // avec d'autre langage
                            FAppFlotteMsg.PlayerFlotte := sfcTokenGet(Content, -3, ' ');



                         end else if FContentPos = 4 then begin
                            // Contient les coordonnées de départ/arrivée
                            GestionMsgFlotteAutreJoueur(Content);

                         end;

                     end;

          end;


       end;

             // Une guerrière flotte  de joueur playerName de la planète planetName [5:260:8]
	          // <a href="writemessages.php?session=1111111&messageziel=00000000">
	          // <img src="http://80.237.203.201/download/use/asgard/img/m.gif" border=0 alt="Ecrire un message"></a>
	          // se rapproche de la planète planetName[5:170:5] Cette flotte est composée de 184 Vaisseauxs. ( 4*Grand transporteur, 180*Vaisseau de bataille) Son ordre est: Attaquer



       // Retour (tout en un message)
       // Une de tes  flottes de la planète planetName 6:95:5 revient de la planète planetName [5:152:6] à sa planète de départ.Sa mission est: Transport


       // Transport allié
       // Une pacifique flotte  de joueur playerName de la planète planetName [2:77:5]
       // <a href="writemessages.php?session=0000000&messageziel=11111111111">
       // <img src="http://80.237.203.201/download/use/asgard/img/m.gif" border=0 alt="Ecrire un message"></a>
       // se rapproche de la planète planetName[2:86:6] Cette flotte est composée de 5 Vaisseauxs. ( 5*Grand transporteur) Son ordre est: Transport


       exit;
    end;

    if FWhatIsNextContent <> CNT_NEXT_CONTENT_UNKNOW then begin

       // Réinitialise la valeur
       xPos := FWhatIsNextContent;
       FWhatIsNextContent := CNT_NEXT_CONTENT_UNKNOW;

       case xPos of
           CNT_NEXT_CONTENT_PLANETNAME: begin
                             // Planète      &quot;PlaneteNom&quot;
                             xPos := pos('&quot;', lowercase(Content));
                             lngPos := 5;

                             if (xPos < 1) then begin
                                xPos := pos('"', lowercase(Content));
                                lngPos := 0;
                             end;


                             if xPos > 0 then begin
                                System.Delete(Content, 1, xPos + lngPos);

                                xPos := pos('&quot;', lowercase(Content));
                                if (xPos < 1) then begin
                                   xPos := pos('"', lowercase(Content));
                                end;

                                if xPos > 0 then begin
                                   System.Delete(Content, xPos, maxint);

                                   FCurrNomPlanete := Content;
                                   FWhatIsNextContent := CNT_NEXT_CONTENT_PSEUDOJOUEUR;

                                end;
                             end;
                             
                         end;

           CNT_NEXT_CONTENT_PSEUDOJOUEUR: begin
                                //  (NickPlayer)
                                xPos := pos('(', Content);
                                if xPos > 0 then begin
                                   System.Delete(Content, 1, xPos);
                                   xPos := pos(')', Content);

                                   if xPos > 0 then begin
                                      System.Delete(Content, xPos, maxint);

                                      FCurrNomJoueur := Content;

                                   end;
                                end;

                         end;

           CNT_NEXT_CONTENT_NEWMESSAGE: begin
                             // Tu as 2 nouveau(x) message(s)s
                             exit;

                         end;

           CNT_NEXT_CONTENT_POINTS: begin
                             // 1045 (Place 4222 de 10915)
                             Content := sfcRemplace(trim(Content), '.', '');
                             ExtractPointClassement(Content);

                             FWhatIsNextContent := CNT_NEXT_CONTENT_POINTS_PLACE;

                         end;

           CNT_NEXT_CONTENT_POINTS_PLACE: begin
                             // Nouveau format de points:
                             // 95248 (Place <a href='stat.php?session=1111111&start=401'>409</a> de 9249)
                             // ici, on ne contient que la place
                             Content := sfcRemplace(trim(Content), '.', '');
                             FClassementPosition := StrToIntDef(Content, -1);

                             FWhatIsNextContent := CNT_NEXT_CONTENT_POINTS_NBPLAYERS;

                         end;

           CNT_NEXT_CONTENT_POINTS_NBPLAYERS: begin
                             // de 9249)
                             Content := trim(Content);
                             Content := sfcRemplace(Content, '.', '');

                             xPos := pos(')', Content);
                             if xPos > 0 then
                                System.Delete(Content, xPos, maxint);

                             xPos := pos(' ', Content);
                             if xPos > 0 then
                                System.Delete(Content, 1, xPos);

                             FClassementTotalPlayers :=  StrToIntDef(Content, -1);

                         end;

           CNT_NEXT_CONTENT_IN_DIAMETRE, CNT_NEXT_CONTENT_IN_DIAMETRE_BUF: begin
                             // Remet le flag, le tampon est traité au début de
                             // la prochaine ligne
                             FWhatIsNextContent := CNT_NEXT_CONTENT_IN_DIAMETRE_BUF;

                             // Ne pas oublier que le parseur supprimer les
                             // espaces de droite et de gauche tout seul
                             FTamponTraitement := FTamponTraitement + Content;
                         end;


           CNT_NEXT_CONTENT_SERVER_TIME: begin
                             // Wed Nov 23 20:55:08
                             FDateServeur := OGDATETIME_StrToUnix(Content);

                             if FDateServeur < 0 then
                                FDateServeur := 0;
                                
                         end;


       end;

       exit;
    end;

    // Les majuscules n'ont plus d'intéret dans la suite
    Content := sfcSupprAccentsAll(lowercase(trim(Content)));



    if SameText(Content, LangParsing.GetData('vuegen_stsa_points', 'points')) then begin
       FWhatIsNextContent := CNT_NEXT_CONTENT_POINTS;

    end else if SameText(Content, LangParsing.GetData('vuegen_stsa_diametre', 'diametre')) then begin
       FWhatIsNextContent := CNT_NEXT_CONTENT_IN_DIAMETRE;

    end else if pos(LangParsing.GetData('apercu_lwpos_heure_serveur', 'heure du serveur'), Content) > 0 then begin
       FWhatIsNextContent := CNT_NEXT_CONTENT_SERVER_TIME;

    end;







end;



function GetVaisseauxStrFromJS(const MsgJS: string; var NbVaisseaux: integer): string;
var xPos: integer;
begin
// <a href='#' onmouseover='
// this.T_WIDTH=150;return escape("Nombre
//de vaisseaux : 138 &lt;br&gt;Petit transporteur 16&lt;br&gt;Grand transporteur 42&lt;br&gt;Chasseur
//léger 20&lt;br&gt;Chasseur lourd 30&lt;br&gt;Croiseur 20&lt;br&gt;Vaisseau de bataille 10&lt;br&gt;")'
//class='attack'>

    Result := MsgJS;



    (*
    xPos := pos('"', Result);
    if xPos = 0 then begin
       Result := 'Erreur';
       exit;
    end;
    System.Delete(Result, 1, xPos);


    xPos := pos('"', Result);
    if xPos = 0 then begin
       Result := 'Erreur';
       exit;
    end;
    System.Delete(Result, xPos, maxint);
    *)

    xPos := pos(':', Result);
    if xPos > 0 then begin
       // contient le nombre de vaisseaux
       System.Delete(Result, 1, xPos);
       Result := trimleft(Result);
       NbVaisseaux := sfcTokenGetInt(Result, 1, ' ', -1);

       xPos := pos(';', Result);
       if xPos > 0 then
          System.Delete(Result, 1, xPos);

    end;

    Result := sfcRemplace(Result, '&lt;br&gt;', '; ');
    Result := sfcRemplace(Result, '<br>', '; ');
    Result := sfcRemplace(Result, '<br />', '; ');
    Result := trim(Result);

end;


(*
procedure TParsingApercu.GestionMsgAutreJoueur(Content: string);
var xPos: integer;
begin

// se rapproche de la planète planetName[2:43:6] Cette flotte est composée de 5 Vaisseauxs. ( 5*Grand transporteur) Son ordre est: Transport
// ou
// se rapproche de la planète planetName[3:253:5] Cette flotte est composée de 184 Vaisseauxs. ( 4*Grand transporteur, 180*Vaisseau de bataille) Son ordre est: Attaquer

   xPos := pos('de la plan', Content);
   if xPos = 0 then begin
      FError := true;
      exit;
   end;
   System.Delete(Content, 1, xPos + length('de la plan'));

   xPos := pos(' ', Content);
   if xPos = 0 then begin
      FError := true;
      exit;
   end;
   System.Delete(Content, 1, xPos);

   xPos := pos('[', Content);
   if xPos = 0 then begin
      FError := true;
      exit;
   end;


   FAppFlotteMsg.ArriveeStr := trim(copy(Content, 1, xPos - 1));

   System.Delete(Content, 1, xPos);

   // 3:253:5] Cette flotte est composée de 184 Vaisseauxs. ( 4*Grand transporteur, 180*Vaisseau de bataille) Son ordre est: Attaquer

   xPos := pos(']', Content);
   if xPos = 0 then begin
      FError := true;
      exit;
   end;
   
   FAppFlotteMsg.Arrivee := mpcExtractPlanetLocation(copy(Content, 1, xPos - 1));

   System.Delete(Content, 1, xPos);


   xPos := pos(' de ', Content);
   if xPos = 0 then begin
      FError := true;
      exit;
   end;

   System.Delete(Content, 1, xPos + length(' de ') - 1);


   // 184 Vaisseauxs. ( 4*Grand transporteur, 180*Vaisseau de bataille) Son ordre est: Attaquer
   xPos := pos(' ', Content);
   if xPos = 0 then begin
      FError := true;
      exit;
   end;

   FAppFlotteMsg.NbVaisseau := StrToIntDef(copy(Content, 1, xPos - 1), -1);

   xPos := pos('(', Content);
   if xPos = 0 then begin
      FError := true;
      exit;
   end;
   System.Delete(Content, 1, xPos);

   xPos := pos(')', Content);

   FAppFlotteMsg.VaisseauxStr := trim(copy(Content, 1, xPos - 1));

   System.Delete(Content, 1, xPos);

   // Son ordre est: Attaquer
   xPos := pos(':', Content);
   if xPos = 0 then begin
      FError := true;
      exit;
   end;
   System.Delete(Content, 1, xPos);

   // Attaquer, Transport, ou encore Espionnage
   FAppFlotteMsg.Ordre := mamOrdreStrToType(Content);

end;
*)




function VerificationIsMoon(PetitePartieDuMsg: string): boolean;
var xPos: integer;
begin

    Result := false;

    // les parentheses sont interdites dans un nom de planete
    // quand il y a des parentheses, c'est pour indiquer que c'est une lune
    // cependant, cela n'est valable uniquement si la planete a ete renomme
    xPos := pos('(', PetitePartieDuMsg);

    if xPos > 0 then begin
       // Dans ce cas là on est certain
       Result := true;

    end else begin
       // on essaye la version habituelle sinon
       // ATTENtiON: cela ne suffit pas, car une planete peut porter le nom "Lune"
       xPos := pos(LangParsing.GetData('vuegen_poslw_lune', 'lune ['), Lowercase(PetitePartieDuMsg));

       if xPos > 0 then begin
          // Verification supplementaire qui consiste à verifier si le mot
          // "planete" n'existe pas dans la phrase
          // on aurait alors "la planète Lune ["

          xPos := pos(LangParsing.GetData('vuegen_poslw_planete', 'plan'), Lowercase(PetitePartieDuMsg));

          if xPos > 0 then begin
             // c'est une planète
             Result := False;

          end else begin
             // c'est bien une lune
             Result := True;
          end;

       end else begin
          // on est certain que ce n'est pas une lune
          Result := false;
       end;

    end;


end;


///////////////////////////////////////////////////
// L'attaque/sondage (rating comme ennemi)
// mais aussi le transport pacifique
// car ils ont le meme format de message
//
// La methode de parsing a été amelioré pour supporter facilement
// plusieurs langue (on supprime directement un nombre de mot précis au
// lieu de rechercher si un mot existe puis de le supprimer)
//
function TParsingApercu.GestionMsgFlotteAutreJoueur(Content: string): boolean;
var sPart: string;
    xPos: integer;
    bIsFromLune, bLocalErreur: boolean;

    DataStr: string;
    DataInt: integer;
begin


    // Pacifique ou allié, le message reste le même car
    // il y a un lien pour envoyer un message ingame au joueur
    // et on utilise le texte qui se situe après ce lien
    // il y a un problème si jamais le mot "pacifique"
    // ou "ennemi" se situe après ce lien.
    // pour l'univers fr, us et es ce n'est pas le cas.

    //ennemy: venant de la planète planetName [1:1:4] atteint la planète planetName [1:1:5]. Elle avait pour mission: Attaquer</span>
    //ennemy: venant de la Lune [1:1:4] atteint la Lune [1:1:5]. Elle avait pour mission: Attaquer</span>
    //  ally: venant de la planète planetName [1:1:6] atteint la planète planetName [1:1:1]. Elle avait pour mission: Transporter

    //  ally: from planet planetName [5:5:12] is approaching planet planetName [5:5:9]. Its mission is: Transport.
    //ennemy: from planet planetName [5:5:8] is approaching planet planetName [5:5:9]. Its mission is: Attack.

    //ennemy: de el planeta planetName [5:5:6] llega a el planeta planetName [5:5:10]. La misión es: Atacar
    //  ally: de el planeta planetName [5:5:6] llega a el planeta planetName [5:5:10]. La misión es: Transportar

    //////////////////////////////////:
    // REMARQUE: cette parti du parsing ne sert à rien car
    // l'interet est d'avoir les coordonnées, ou plus exactement,
    // savoir que l'on est attaqué et connaitre la durée de l'impact
    // suffit largement pour le robot.
    // Tout le reste (sauf les coordonnées d'impact) est inutile (surtout
    // les noms de planete où l'on se casse la tête pour les trouver)
    // Seul le fait de savoir si c'est une lune ou pas la planete de destination
    // est interessant.

    ///////////////////////////////////////
    // REMARQUE 2:
    // Avec la nouvelle methode d'identificaton de lune, on ne verifie
    // pas si le mot planete existe. Un joueur malin peut donc faire
    // croire qu'il attaque d'une lune sans en avoir.
    // MAIS cela n'est pas important car le but est d'effectuer
    // l'évacuation de flotte, pas de contre attaquer ^^
    // cependant, c'est assez génant.
    

    bIsFromLune := false;
    bLocalErreur := false;
    Result := false;


    xPos := pos('[', Content);
    if xPos = 0 then  begin
       FError := true;
       exit;
    end;

    // inclu le [
    sPart := copy(Content, 1, xPos);
    System.Delete(Content, 1, xPos);


    // Extrait le nom de la planète de départ (celle du joueur adverse)
    // on commence par verifier si ce n'est pas une lune
    //xPos := pos(LangParsing.GetData('vuegen_poslw_lune', 'lune ['), Lowercase(sPart));



    if VerificationIsMoon(sPart) then begin
       // lune
       FAppFlotteMsg.DepartStr := LangParsing.GetData('Lune', 'Lune');
       bIsFromLune := true;

    end else begin
       // Sinon c'est à partir d'une planète
       // il n'y a que le sens aller pour les flottes ennemies/pacifiques
       // venant de la planète scout171 [5:87:4]
       DataStr := LangParsing.GetData('vuegeneral_ennflotte_msg_aller_premier', '5');

       try
          DataInt := StrToInt(DataStr);
       except
          DataInt := maxint;
       end;

       if DataInt = maxint then begin
          // erreur du fichier langue
          // ce n'est pas une erreur de parsing
          // on essaie de corriger l'erreur...
          FError := true;
          bLocalErreur := true;
          DataInt := 2;
       end;


       // extrait le nom de la planete
       DataInt := -1 * DataInt;
       sPart := sfcTokenGet(sPart, DataInt, ' ');

       // Supprime le " ["
       System.Delete(sPart, length(sPart) - 1, maxint);

       FAppFlotteMsg.DepartStr := trim(sPart);

       if bLocalErreur then
          FAppFlotteMsg.DepartStr := FAppFlotteMsg.DepartStr + LANG_PLANET_PARSING_ADD_INVALID;

    end;

    xPos := pos(']', Content);
    if xPos = 0 then  begin
       FError := true;
       exit;
    end;

    // extrait les coordonnées
    FAppFlotteMsg.Depart := mpcExtractPlanetLocation(copy(Content, 1, xPos - 1));

    if bIsFromLune then begin
       FAppFlotteMsg.Depart.Position := FAppFlotteMsg.Depart.Position + CNT_POSITION_LUNE;
    end;
    System.Delete(Content, 1, xPos);
    Content := trimleft(Content);


    ///////////////////////////////////////////////////:
    // Planete cible
    //
    bIsFromLune := false;
    bLocalErreur := false;

    xPos := pos('[', Content);
    if xPos = 0 then begin
       FError := true;
       exit;
    end;

    // inclu le [
    sPart := copy(Content, 1, xPos);
    System.Delete(Content, 1, xPos);


    //xPos := pos(LangParsing.GetData('vuegen_poslw_lune', 'lune ['), Lowercase(sPart));

    if VerificationIsMoon(sPart) then begin
       FAppFlotteMsg.ArriveeStr := LangParsing.GetData('Lune', 'Lune');
       bIsFromLune := true;

    end else begin
       // Sinon c'est à partir d'une planète

       DataStr := LangParsing.GetData('vuegeneral_ennflotte_msg_aller_second', '4');

       try
          DataInt := StrToInt(DataStr);
       except
          DataInt := maxint;
       end;

       if DataInt = maxint then begin
          // erreur du fichier langue
          // ce n'est pas une erreur de parsing
          // on essaie de corriger l'erreur...
          FError := true;
          bLocalErreur := true;
          DataInt := 2;
       end;


       // extrait le nom de la planete
       DataInt := -1 * DataInt;
       sPart := sfcTokenGet(sPart, DataInt, ' ');

       // Supprime le " ["
       System.Delete(sPart, length(sPart) - 1, maxint);

       FAppFlotteMsg.ArriveeStr := trim(sPart);

       if bLocalErreur then
          FAppFlotteMsg.ArriveeStr := FAppFlotteMsg.ArriveeStr + LANG_PLANET_PARSING_ADD_INVALID;

    end;

    xPos := pos(']', Content);
    if xPos = 0 then  begin
       FError := true;
       exit;
    end;

    // extrait les coordonnées
    FAppFlotteMsg.Arrivee  := mpcExtractPlanetLocation(copy(Content, 1, xPos - 1));

    if bIsFromLune then begin
       FAppFlotteMsg.Arrivee.Position := FAppFlotteMsg.Arrivee.Position + CNT_POSITION_LUNE;
    end;
    System.Delete(Content, 1, xPos);
    Content := trimleft(Content);

    

    Result := true;


    ///////////////////////////////
    // Extrait la mission

    if (FAppFlotteMsg.Ordre = ooNeant) or FOverrideSpanClassOrdre then begin
       // la mission n'a pas été détecté à partir du SPAN class
       // Content = ". Elle avait pour mission: Attaquer"
       xPos := pos(':', Content);
       if xPos = 0 then  begin
          FError := true;
          exit;
        end;

        System.Delete(Content, 1, xPos);
        Content := trim(Content);
        
        FAppFlotteMsg.Ordre := mamOrdreStrToType(Content);

        if mamIsAttackGroupee(Content) then begin
           // c'est une attaque groupee
           FCurrAttackGroup := 1;
        end;
    end;

end;



///////////////////////////////////////////////////
// Tous les messages de nos propres flottes
//
// La methode de parsing a été amelioré pour supporter facilement
// plusieurs langue (on supprime directement un nombre de mot précis au
// lieu de rechercher si un mot existe puis de le supprimer)
//
function TParsingApercu.GestionMsgFlotteLaNotre(Content: string): boolean;
var DefineIsRetour: string;
    DataStr: string;
    DataInt: integer;

    bLocalErreur: boolean;

    xPos: integer;
    sPart: string;
    bIsFromLune: boolean;
    bIsFromDebris: boolean;
begin
    // venant de la planète p1 [5:6:7] atteint la  lune [5:4:3]. Elle avait pour mission:
    // venant de la planète p2 [1:2:3] atteint la planète p3 [4:5:6]. Elle avait pour mission:

    // rentre de la  Champ de débris [5:5:9] à la  lune [5:5:5]. Elle avait pour mission:
    // rentre de la planète p3 [4:5:6] à la planète p4 [4:5:7]. Elle avait pour mission:

    Result := false;

    if (FAppFlotteMsg.Direction = odNeant) or FOverrideSpanClassDirection then begin
       DefineIsRetour := LangParsing.GetData('vuegen_known_retour_method', 'r');
       DataStr        := LangParsing.GetData('vuegen_known_retour_data', 'rentre de la');

       if pos(DataStr, Content) > 0 then begin
          if SameText(DefineIsRetour, 'r') then
             FAppFlotteMsg.Direction := odRetour
          else
             FAppFlotteMsg.Direction := odAller;

       end else begin
          if SameText(DefineIsRetour, 'r') then
             FAppFlotteMsg.Direction := odAller
          else
             FAppFlotteMsg.Direction := odRetour;
       end;
    end;


    ///////////////////////////////////
    // ATTENTION:
    // En français "venant de la" et "rentre de la"
    // tienne sur un même nombre de mot, MAIS ce n'est peut-être
    // pas le cas pour les autres langue
    // En espagnol:
    // de el planeta planetName [1:123:12] llega a el planeta planetName [3:123:4]. La misión es:
    // vuelve de el planeta planetName [3:1:4] a el planeta planetName [3:123:12]. La misión era:
    //
    // On a 2 mots pour l'aller, et 3 pour le retour.
    ////////////////////////////////////

    xPos := pos('[', Content);

    // conserve le ]
    sPart := copy(Content, 1, xPos);
    System.Delete(Content, 1, xPos);




    // on commence par verifier si ce n'est pas une lune
(*
    // les parentheses sont interdites dans un nom de planete
    // quand il y a des parentheses, c'est pour indiquer que c'est une lune
    // cependant, cela n'est valable uniquement si la planete a ete renomme
    xPos := pos(LangParsing.GetData('('), Lowercase(sPart));

    if xPos = 0 then begin
       // on essaye la version habituelle sinon
       // ATTENtiON: cela ne suffit pas, car une planete peut porter le nom "Lune"
       xPos := pos(LangParsing.GetData('vuegen_poslw_lune', 'lune ['), Lowercase(sPart));
    end;
*)


    bIsFromLune   := false;
    bIsFromDebris := false;
    bLocalErreur  := false;

    if VerificationIsMoon(sPart) then begin
       // c'est une lune
       FAppFlotteMsg.DepartStr := LangParsing.GetData('Lune', 'Lune');
       bIsFromLune := true;

    end else begin
       // maintenant il se peut que c'est un champ de débris
       if FAppFlotteMsg.Ordre = ooExploiter then begin
          if FAppFlotteMsg.Direction = odAller then begin
             // le mot "champ de debris" apparaitra dans le champ "planete d'arriver"

          end else begin
             // le mot "champ  de debris" doit correspond au champ actuel
             // on effectue une simple verification
             xPos := pos(LangParsing.GetData('vuegen_poslw_debris', 'champ'), Lowercase(sPart));
             if xPos > 0 then begin
                FAppFlotteMsg.DepartStr := LangParsing.GetData('vuegen_affiche_debris', 'Champ de débris');
                bIsFromDebris := true;
             end;

          end;
       end;

       if bIsFromDebris = false then begin
          // Sinon c'est à partir d'une planète



          if FAppFlotteMsg.Direction = odAller then
             // venant de la planète planetName [
             DataStr := LangParsing.GetData('vuegeneral_ownflotte_msg_aller_premier', '5')

          else
             // rentre de la planète planetName [
             DataStr := LangParsing.GetData('vuegeneral_ownflotte_msg_retour_premier', '5');

          try
             DataInt := StrToInt(DataStr);
          except
             DataInt := maxint;
          end;

          if DataInt = maxint then begin
             // erreur du fichier langue
             // ce n'est pas une erreur de parsing
             // on essaie de corriger l'erreur...
             FError := true;
             bLocalErreur := true;
             DataInt := 2;
          end;

          DataInt := -1 * DataInt;
          sPart := sfcTokenGet(sPart, DataInt, ' ');

          // Supprime le " ["
          System.Delete(sPart, length(sPart) - 1, maxint);

          FAppFlotteMsg.DepartStr := trim(sPart);

          if bLocalErreur then
             FAppFlotteMsg.DepartStr := FAppFlotteMsg.DepartStr + LANG_PLANET_PARSING_ADD_INVALID;

       end;

    end;


    xPos := pos(']', Content);
    if xPos = 0 then  begin
       FError := true;
       exit;
    end;

    // extrait les coordonnées
    FAppFlotteMsg.Depart := mpcExtractPlanetLocation(copy(Content, 1, xPos - 1));

    if bIsFromLune then begin
       FAppFlotteMsg.Depart.Position := FAppFlotteMsg.Depart.Position + CNT_POSITION_LUNE;
    end else if bIsFromDebris then begin
       // on devrait ajouter quelque chose ?

    end;

    System.Delete(Content, 1, xPos);
    Content := trimleft(Content);



    ///////////////////////////////////////////////////:
    // Planete cible
    //

    // atteint la  lune [5:5:5]. Elle avait pour mission:
    // à la  lune [5:5:5]. Elle avait pour mission:
    // à la planète p1 [4:5:6]. Elle avait pour mission:
    // a el planeta planetName [3:2:1]. La misión era:
    
    xPos := pos('[', Content);

    // conserve le [
    sPart := copy(Content, 1, xPos);
    System.Delete(Content, 1, xPos);

    // on commence par verifier si ce n'est pas une lune
    //xPos := pos(LangParsing.GetData('vuegen_poslw_lune', 'lune ['), Lowercase(sPart));

    bIsFromLune   := false;
    bIsFromDebris := false;
    bLocalErreur  := false;



    if VerificationIsMoon(sPart) then begin
       // c'est une lune
       FAppFlotteMsg.ArriveeStr := LangParsing.GetData('Lune', 'Lune');
       bIsFromLune := true;

    end else begin
       // maintenant il se peut que c'est un champ de débris
       if FAppFlotteMsg.Ordre = ooExploiter then begin
          if FAppFlotteMsg.Direction = odRetour then begin
             // le mot "champ de debris" a du apparaitre dans le champ "planete de depart"

          end else begin
             // le mot "champ  de debris" doit correspondre au champ actuel
             // on effectue une simple verification

             xPos := pos(LangParsing.GetData('vuegen_poslw_debris', 'champ'), lowercase(sPart));
             if xPos > 0 then begin
                FAppFlotteMsg.ArriveeStr := LangParsing.GetData('vuegen_affiche_debris', 'Champ de débris');
                bIsFromDebris := true;
             end;

          end;
       end;

       if bIsFromDebris = false then begin
          // Sinon elle atteint une planète


          if FAppFlotteMsg.Direction = odAller then
             // atteint la planète planetName [
             DataStr := LangParsing.GetData('vuegeneral_ownflotte_msg_aller_second', '4')

          else
             // à la planète planetName
             DataStr := LangParsing.GetData('vuegeneral_ownflotte_msg_retour_second', '4');


          try
             DataInt := StrToInt(DataStr);
          except
             DataInt := maxint;
          end;

          if DataInt = maxint then begin
             // erreur du fichier langue
             // ce n'est pas une erreur de parsing
             // on essaie de corriger l'erreur...
             FError  := true;
             bLocalErreur := true;
             DataInt := 2;
          end;

          DataInt := -1 * DataInt;
          sPart := sfcTokenGet(sPart, DataInt, ' ');

          // Supprime le " ["
          System.Delete(sPart, length(sPart) - 1, maxint);

          FAppFlotteMsg.ArriveeStr := trim(sPart);

          if bLocalErreur then
             FAppFlotteMsg.ArriveeStr := FAppFlotteMsg.ArriveeStr + LANG_PLANET_PARSING_ADD_INVALID;

       end;

    end;


    xPos := pos(']', Content);
    if xPos = 0 then  begin
       FError := true;
       exit;
    end;


    // extrait les coordonnées
    FAppFlotteMsg.Arrivee := mpcExtractPlanetLocation(copy(Content, 1, xPos - 1));

    if bIsFromLune then begin
       FAppFlotteMsg.Arrivee.Position := FAppFlotteMsg.Arrivee.Position + CNT_POSITION_LUNE;
    end else if bIsFromDebris then begin
       // on devrait ajouter quelque chose ?

    end;

    System.Delete(Content, 1, xPos);
    Content := trimleft(Content);



    Result := true;


    ///////////////////////////////
    // Extrait la mission

    if (FAppFlotteMsg.Ordre = ooNeant) or FOverrideSpanClassOrdre then begin
       // la mission n'a pas été détecté à partir du SPAN class
       // Content = ". Elle avait pour mission: Attaquer"
       xPos := pos(':', Content);
       if xPos = 0 then  begin
          // la mission est probablement dans le OnContent suivant
          exit;
        end;

        System.Delete(Content, 1, xPos);
        Content := trim(Content);
        
        FAppFlotteMsg.Ordre := mamOrdreStrToType(Content);
    end;

end;


destructor TParsingApercu.Destroy;
begin

    FMessageList.Free;

    inherited;
end;


constructor TParsingApercu.Create;
begin
    inherited;

    // Rien à initialiser, mis à part ce qui est fait lorsque l'on parse les données
    //FTypeClass := CLASSTYPE_APPERCU;

    FMessageList := TCollectionAppMessage.Create;

    
    FUseSpanClass_AND_MsgGame_If_Fail := false;

    FOverrideSpanClassOrdre     := false;
    FOverrideSpanClassDirection := false;

end;


end.
